package com.asha.md360player4android.vr.plugins;

import android.content.Context;
import android.opengl.GLES20;
import android.opengl.Matrix;

import com.asha.md360player4android.vr.objects.MDCircleExtra;
import com.asha.vrlib.MD360Director;
import com.asha.vrlib.MD360DirectorFactory;
import com.asha.vrlib.MD360Program;
import com.asha.vrlib.MDVRLibrary;
import com.asha.vrlib.model.MDMainPluginBuilder;
import com.asha.vrlib.model.MDPosition;
import com.asha.vrlib.objects.MDAbsObject3D;
import com.asha.vrlib.objects.MDObject3DHelper;
import com.asha.vrlib.plugins.MDAbsPlugin;
import com.asha.vrlib.plugins.MDDrawingCache;
import com.asha.vrlib.strategy.projection.ProjectionModeManager;
import com.asha.vrlib.texture.MD360Texture;

import static com.asha.vrlib.common.GLUtil.glCheck;

/**
 * Created by yao.fu on 17-4-13.
 */

public class FYPanoramaPluginEx extends MDAbsPlugin {
    private MD360Program mProgram;

    private MD360Program mBitmapProgram;

    private MD360Texture mTexture;

    private ProjectionModeManager mProjectionModeManager;

    private static final MDPosition position = MDPosition.newInstance().setZ(-2f);

    private MDCircleExtra mCircleObject;

    private MD360Director mFixedDirector;

    private MDDrawingCache mDrawingCache;

    public FYPanoramaPluginEx(MDMainPluginBuilder builder) {
        mTexture = builder.getTexture();
        mProgram = new MD360Program(builder.getContentType());
        mBitmapProgram = new MD360Program(MDVRLibrary.ContentType.BITMAP);

        mProjectionModeManager = builder.getProjectionModeManager();

        mFixedDirector = new OrthogonalImpl().createDirector(0);

        mCircleObject = new MDCircleExtra();
        mDrawingCache = new MDDrawingCache();
    }

    @Override
    public void initInGL(Context context) {
        mProgram.build(context);
        mBitmapProgram.build(context);
        mTexture.create();

        MDObject3DHelper.loadObj(context, mCircleObject);
    }

    @Override
    public void beforeRenderer(int totalWidth, int totalHeight) {
        mFixedDirector.updateViewport(totalWidth, totalHeight);
        mDrawingCache.bind(totalWidth, totalHeight);
        drawConverter(totalWidth, totalHeight);
        mDrawingCache.unbind();
    }

    @Override
    public void renderer(int index, int width, int height, MD360Director director) {
        MDAbsObject3D object3D = mProjectionModeManager.getObject3D();
        // check obj3d
        if (object3D == null) return;

        // Update Projection
        director.updateViewport(width, height);

        // Set our per-vertex lighting program.
        mBitmapProgram.use();
        glCheck("MDPanoramaPlugin mProgram use");

        // mTexture.texture(mProgram);
        GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
        GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mDrawingCache.getTextureOutput());

        object3D.uploadVerticesBufferIfNeed(mBitmapProgram, index);
        object3D.uploadTexCoordinateBufferIfNeed(mBitmapProgram, index);

        // Pass in the combined matrix.
        director.shot(mBitmapProgram, getModelPosition());
        object3D.draw();
    }

    @Override
    public void destroyInGL() {
        mTexture = null;
    }

    @Override
    protected MDPosition getModelPosition() {
        return mProjectionModeManager.getModelPosition();
    }

    @Override
    protected boolean removable() {
        return false;
    }

    private void drawConverter(int width, int height) {
        //GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);
        glCheck("FYPanoramaPluginEx glClear");

        GLES20.glViewport(0, 0, width, height);
        GLES20.glEnable(GLES20.GL_SCISSOR_TEST);
        GLES20.glScissor(0, 0, width, height);

        mProgram.use();
        mTexture.texture(mProgram);

        mFixedDirector.updateViewport(width, height);
        mCircleObject.uploadVerticesBufferIfNeed(mProgram, 0);
        mCircleObject.uploadTexCoordinateBufferIfNeed(mProgram, 0);

        // Pass in the combined matrix.
        mFixedDirector.shot(mProgram, position);

        mCircleObject.draw();

        GLES20.glDisable(GLES20.GL_SCISSOR_TEST);
    }

    public class OrthogonalImpl extends MD360DirectorFactory {

        @Override
        public MD360Director createDirector(int index) {
            switch (index) {
                default:
                    return new OrthogonalDirector(new MD360Director.Builder());
            }
        }
    }

    private class OrthogonalDirector extends MD360Director {

        private OrthogonalDirector(Builder builder) {
            super(builder);
            setEyeZ(-200);
        }

        @Override
        public void setDeltaX(float mDeltaX) {
            // nop
        }

        @Override
        public void setDeltaY(float mDeltaY) {
            // nop
        }

        @Override
        public void updateSensorMatrix(float[] sensorMatrix) {
            // nop
        }

        @Override
        protected void updateProjection() {
            final float left = -0.5f;
            final float right = 0.5f;
            final float bottom = -0.5f;
            final float top = 0.5f;
            final float far = 500;
            Matrix.orthoM(getProjectionMatrix(), 0, left, right, bottom, top, getNear(), far);
        }
    }
}
